/* NOTICE
    OpenJaWS - Open Java Weather Station
    
    Copyright (C) 2008 Grant Gardner <grant@lastweekend.com.au>
    
    OpenJaWS is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
    
NOTICE */

package au.com.lastweekend.ws2300.proxy;

import java.io.IOException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import au.com.lastweekend.openjaws.util.StringUtil;
import au.com.lastweekend.ws2300.Device;

public class MemoryDevice extends Device {

    private static final Logger LOG = LoggerFactory.getLogger(MemoryDevice.class);

    byte[] memory = new byte[MAX_ADDRESS + 1];

    public MemoryDevice() {

    }

    public MemoryDevice(MemoryDevice memDevice) {

        System.arraycopy(memDevice.memory, 0, this.memory, 0, memDevice.memory.length);
    }

    public synchronized byte[] read(int address, int numBytes) throws IOException {

        byte[] resultNibbles = new byte[numBytes * 2];

        try {
            for (int i = 0; i < numBytes; i++) {
                resultNibbles[2 * i] = (byte) (memory[address + (2 * i)] & 0x0F);
                resultNibbles[(2 * i) + 1] = (byte) (memory[address + (2 * i) + 1] & 0x0F);
            }
        } catch (RuntimeException e) {
            throw newIOException("Exception in read(" + Integer.toHexString(address) + "," + numBytes + ")", e);
        }
        return resultNibbles;
    }

    public synchronized void write(int nibbleAddress, byte[] nibbles) throws IOException {

        int numNibbles = nibbles.length;

        try {
            System.arraycopy(nibbles, 0, memory, nibbleAddress, numNibbles);
        } catch (RuntimeException e) {
            throw newIOException(String.format("Exception in write(%#04X,%d)", nibbleAddress, numNibbles), e);
        }

        LOG.debug(String.format("write(%#04X,%d,%s)", nibbleAddress, numNibbles, StringUtil.toHexBytes(nibbles, 0, numNibbles)));

    }

    public synchronized void writeBit(int nibbleAddress, int bitAddress, boolean setBit) throws IOException {

        int bitMask = (0x01 << bitAddress);

        try {
            if (setBit) {
                memory[nibbleAddress] = (byte) (memory[nibbleAddress] | bitMask);
            } else {
                memory[nibbleAddress] = (byte) (memory[nibbleAddress] & (~bitMask));
            }
        } catch (RuntimeException e) {
            throw newIOException(String.format("Exception in writeBit(%#04X,%d,%b)", nibbleAddress, bitAddress, setBit), e);
        }

        LOG.debug(String.format("writeBit(%#04X,%d,%b)", nibbleAddress, bitAddress, setBit));

    }

}
